<?php
declare(strict_types=1);


namespace App\Fastapp\Mapper;

use App\Fastapp\Api\Service\Account\AccountSettingService;
use App\Fastapp\Model\Account;
use App\Fastapp\Model\AccountInviteLevel;
use App\Fastapp\Model\AccountRecharge;
use App\Fastapp\Model\AccountWallet;
use App\Fastapp\Model\AccountWalletLog;
use App\Fastapp\Model\AccountWithdrawal;
use App\Fastapp\Model\FastappChannel;
use App\Fastapp\Model\FastappChannelAgent;
use Hyperf\Database\Model\Builder;
use Mine\Abstracts\AbstractMapper;

/**
 * 用户账号表Mapper类
 */
class FastappAccountMapper extends AbstractMapper
{
    /**
     * @var Account
     */
    public $model;

    public function assignModel()
    {
        $this->model = Account::class;
    }

    /**
     * 搜索处理器
     * @param Builder $query
     * @param array $params
     * @return Builder
     */
    public function handleSearch(Builder $query, array $params): Builder
    {
        if (isset($params['created_at']) && filled($params['created_at']) && is_array($params['created_at']) && count($params['created_at']) == 2) {
            $query->whereBetween(
                'created_at',
                [$params['created_at'][0], $params['created_at'][1]]
            );
        }
        if (isset($params['username']) && filled($params['username'])) {
            $query->where('username', 'like', '%' . $params['username'] . '%');
        }
        if (isset($params['mobile']) && filled($params['mobile'])) {
            $query->where('mobile', 'like', '%' . $params['mobile'] . '%');
        }
        if (isset($params['email']) && filled($params['email'])) {
            $query->where('email', 'like', '%' . $params['email'] . '%');
        }
        if (isset($params['status']) && filled($params['status'])) {
            $query->where('account.status', '=', $params['status']);
        }
        if (isset($params['type']) && filled($params['type'])) {
            $query->where('type', '=', $params['type']);
        }
        if (isset($params['gene_id']) && filled($params['gene_id'])) {
            $query->where('gene_id', '=', $params['gene_id']);
        }
        if (isset($params['parent_id']) && filled($params['parent_id'])) {
            $uids = AccountInviteLevel::query()->where(['parent_id' => $params['parent_id']])->pluck('user_id');
            $query->whereIn('gene_id', $uids);
        }
        if (isset($params['no']) && filled($params['no'])) {
            $query->where('no', '=', $params['no']);
        }
        $with = [
            'recharge', 'withdrawal', 'transaction',
            'profit', 'settingPassword:user_id,val',
            'settingWithdrawalRechargeRate:user_id,val',
            'parent' => function ($query) {
                $query->with(['parent:gene_id,invite_code'])->select(['user_id', 'parent_id']);
            },
            'childrenNum' => function ($query) {
                $query->with(['isRecharge'])->select(['user_id', 'parent_id']);
            }
        ];
        $query->selectRaw('account.*');
        $admin_id = user()->getId();
        if (!user()->isAdminRole() && $admin_id != env('SUPER_ADMIN')) {
            $roles = array_column(user()->getUserRole(), 'code');
            if (!in_array('demo', $roles)) if (in_array('channel', $roles)) $query->where('channel', FastappChannel::query()->where(['admin_id' => $admin_id])->value('id'));
            else if (in_array('agent', $roles)) {
                $agent_user_id = FastappChannelAgent::query()->where(['admin_id' => $admin_id])->value('user_id');
                if (!$agent_user_id) return $query->whereRaw('1=0');
                $link = AccountInviteLevel::query()->where(['user_id' => $agent_user_id])->value('link');
                if ($link) $link .= '.' . $agent_user_id . '%'; else  $link = $agent_user_id . '|%';
                $query->join('account_invite_level as b', 'account.gene_id', '=', 'b.user_id')->where('link', 'like', $link);
            } else $query->where('id', 0);
        }
        return $query->with($with)->orderByDesc('account.id');
    }

    public function detail(int $id): array
    {
        $md = Account::query()->with(['info', 'realname' => function ($query) {
            $query->with(['realname']);
        }])->find($id);
        $data = $md->toArray();
        $data['realname'] = $md->realname?->realname;
        return $data;
    }

    public function children(array $params): array
    {
        $pag = AccountInviteLevel::query()->with(['account'])->where(['parent_id' => $params['user_id']])->paginate(
            (int)($params['pageSize'] ?? $this->model::PAGE_SIZE),
            ['*'],
            'page',
            (int)($params['page'] ?? 1)
        );

        return $this->setPaginate($pag, $params);
    }

    public function handlePageItems(array $items, array $params): array
    {
        if (empty($params['user_id'])) {
            foreach ($items as $item) {
                $item->recharge_amount = nfmt($item->recharge->amount ?: 0);
                $item->transaction_amount = nfmt($item->transaction->amount ?: 0);
                $item->withdrawal_amount = nfmt($item->withdrawal->amount ?: 0);
                $item->profit_amount = nfmt($item->profit->amount ?: 0);
                $item->yk = bcsub($item->profit_amount, $item->transaction_amount, 2);
                $item->child_num = $item->childrenNum->count();
                $n = 0;
                foreach ($item->childrenNum as $v) if ($v->is_recharge) $n++;
                $item->child_num_recharge = $n;
                $item->setHidden(['childrenNum', 'password']);
            }
            return $items;
        }
        $list = [];
        foreach ($items as $item) {
            $list [] = $item->account;
        }
        return $list;
    }

    public function setSetting(array $params): bool|int
    {
        return AccountSettingService::upOrCreate($params['key'], $params['val'], $params['user_id']);
    }

    public function statistics(): array
    {
        $recharge_amount = AccountRecharge::query()->where(['status' => 1])->sum('amount');
        $recharge_amount_pump = AccountRecharge::query()->where(['status' => 1])->sum('pump');
        $withdrawal_amount = AccountWithdrawal::query()->where(['status' => 1])->sum('amount');
        $withdrawal_amount_pump = AccountWithdrawal::query()->where(['status' => 1])->sum('pump');
        $log_amount = AccountWalletLog::query()
            ->where(['type' => AccountWalletLog::USE_BALANCE, 'field' => 'balance'])->sum('amount');
        $log_amount_profit = AccountWalletLog::query()
            ->where(['type' => AccountWalletLog::RECHARGE, 'field' => 'balance'])
            ->whereIn('object_type', [3, 4, 5, 6, 71])->sum('amount');
        $wallet_amount = AccountWallet::query()->sum('balance');
        return [
            'recharge_amount' => nfmt($recharge_amount),
            'recharge_amount_pump' => nfmt($recharge_amount_pump),
            'withdrawal_amount' => nfmt($withdrawal_amount),
            'withdrawal_amount_pump' => nfmt($withdrawal_amount_pump),
            'log_amount' => nfmt($log_amount),
            'log_amount_profit' => nfmt($log_amount_profit),
            'wallet_amount' => nfmt($wallet_amount),
            'yk' => bcsub((string)$recharge_amount, (string)array_sum([$recharge_amount_pump, $withdrawal_amount, $log_amount_profit]), 2),
        ];
    }
}